/*
 *  Copyright 2022 Collate.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *  http://www.apache.org/licenses/LICENSE-2.0
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

import { PlusOutlined } from '@ant-design/icons';
import { Button, Form, Space, Typography } from 'antd';
import { FormProps, useForm } from 'antd/lib/form/Form';
import { UserTag } from 'components/common/UserTag/UserTag.component';
import { UserTagSize } from 'components/common/UserTag/UserTag.interface';
import { ENTITY_NAME_REGEX } from 'constants/regex.constants';
import { EntityReference } from 'generated/type/entityLineage';
import { FieldProp, FieldTypes } from 'interface/FormUtils.interface';
import { toString } from 'lodash';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { getEntityName } from 'utils/EntityUtils';
import { generateFormFields, getField } from 'utils/formUtils';
import { PageLayoutType } from '../../enums/layout.enum';
import { CreateGlossary } from '../../generated/api/data/createGlossary';
import { getCurrentUserId } from '../../utils/CommonUtils';
import TitleBreadcrumb from '../common/title-breadcrumb/title-breadcrumb.component';
import PageLayout from '../containers/PageLayout';
import { AddGlossaryProps } from './AddGlossary.interface';

const AddGlossary = ({
  header,
  allowAccess = true,
  isLoading,
  slashedBreadcrumb,
  onCancel,
  onSave,
}: AddGlossaryProps) => {
  const { t } = useTranslation();
  const [form] = useForm();

  const selectedOwner = Form.useWatch<EntityReference | undefined>(
    'owner',
    form
  );
  const reviewersList =
    Form.useWatch<EntityReference[]>('reviewers', form) ?? [];

  const handleSave: FormProps['onFinish'] = (formData) => {
    const {
      name,
      displayName,
      description,
      tags,
      mutuallyExclusive,
      reviewers = [],
      owner,
    } = formData;

    const selectedOwner = owner ?? {
      id: getCurrentUserId(),
      type: 'user',
    };
    const data: CreateGlossary = {
      name: name.trim(),
      displayName: displayName?.trim(),
      description: description,
      reviewers: reviewers
        .map((d: EntityReference) => toString(d.fullyQualifiedName))
        .filter(Boolean),
      owner: selectedOwner,
      tags: tags || [],
      mutuallyExclusive: Boolean(mutuallyExclusive),
    };
    onSave(data);
  };

  const rightPanel = (
    <>
      <Typography.Title level={5}>
        {t('label.configure-entity', {
          entity: t('label.glossary'),
        })}
      </Typography.Title>
      <Typography.Text className="mb-5">
        {t('message.create-new-glossary-guide')}
      </Typography.Text>
    </>
  );

  const formFields: FieldProp[] = [
    {
      name: 'name',
      id: 'root/name',
      label: t('label.name'),
      required: true,
      placeholder: t('label.name'),
      type: FieldTypes.TEXT,
      props: {
        'data-testid': 'name',
      },
      rules: [
        {
          pattern: ENTITY_NAME_REGEX,
          message: t('message.entity-name-validation'),
        },
        {
          min: 1,
          max: 128,
          message: `${t('message.entity-maximum-size', {
            entity: `${t('label.name')}`,
            max: '128',
          })}`,
        },
      ],
    },
    {
      name: 'displayName',
      id: 'root/displayName',
      label: t('label.display-name'),
      required: false,
      placeholder: t('label.display-name'),
      type: FieldTypes.TEXT,
      props: {
        'data-testid': 'display-name',
      },
    },
    {
      name: 'description',
      required: true,
      label: t('label.description'),
      id: 'root/description',
      type: FieldTypes.DESCRIPTION,
      props: {
        'data-testid': 'description',
        initialValue: '',
        height: '170px',
        readonly: !allowAccess,
      },
    },
    {
      name: 'tags',
      required: false,
      label: t('label.tag-plural'),
      id: 'root/tags',
      type: FieldTypes.TAG_SUGGESTION,
      props: {
        'data-testid': 'tags-container',
      },
    },
    {
      name: 'mutuallyExclusive',
      label: t('label.mutually-exclusive'),
      type: FieldTypes.SWITCH,
      required: false,
      props: {
        'data-testid': 'mutually-exclusive-button',
      },
      id: 'root/mutuallyExclusive',
      formItemLayout: 'horizontal',
    },
  ];

  const ownerField: FieldProp = {
    name: 'owner',
    id: 'root/owner',
    required: false,
    label: t('label.owner'),
    type: FieldTypes.USER_TEAM_SELECT,
    props: {
      hasPermission: true,
      children: (
        <Button
          data-testid="add-owner"
          icon={<PlusOutlined style={{ color: 'white', fontSize: '12px' }} />}
          size="small"
          type="primary"
        />
      ),
    },
    formItemLayout: 'horizontal',
    formItemProps: {
      valuePropName: 'owner',
      trigger: 'onUpdate',
    },
  };

  const reviewersField: FieldProp = {
    name: 'reviewers',
    id: 'root/reviewers',
    required: false,
    label: t('label.reviewer-plural'),
    type: FieldTypes.USER_MULTI_SELECT,
    props: {
      hasPermission: true,
      popoverProps: { placement: 'topLeft' },
      children: (
        <Button
          data-testid="add-reviewers"
          icon={<PlusOutlined style={{ color: 'white', fontSize: '12px' }} />}
          size="small"
          type="primary"
        />
      ),
    },
    formItemLayout: 'horizontal',
    formItemProps: {
      valuePropName: 'selectedUsers',
      trigger: 'onUpdate',
      initialValue: [],
    },
  };

  return (
    <PageLayout
      classes="tw-max-w-full-hd tw-h-full tw-pt-4"
      header={<TitleBreadcrumb titleLinks={slashedBreadcrumb} />}
      layout={PageLayoutType['2ColRTL']}
      pageTitle={t('label.add-entity', { entity: t('label.glossary') })}
      rightPanel={rightPanel}>
      <div className="tw-form-container glossary-form">
        <Typography.Title data-testid="form-heading" level={5}>
          {header}
        </Typography.Title>
        <div className="tw-pb-3" data-testid="add-glossary">
          <Form form={form} layout="vertical" onFinish={handleSave}>
            {generateFormFields(formFields)}
            <div className="m-t-xss">
              {getField(ownerField)}
              {selectedOwner && (
                <div className="tw-my-2" data-testid="owner-container">
                  <UserTag
                    id={selectedOwner.id}
                    name={getEntityName(selectedOwner)}
                    size={UserTagSize.small}
                  />
                </div>
              )}
            </div>
            <div className="m-t-xss">
              {getField(reviewersField)}
              {Boolean(reviewersList.length) && (
                <Space
                  wrap
                  className="tw-my-2"
                  data-testid="reviewers-container"
                  size={[8, 8]}>
                  {reviewersList.map((d, index) => (
                    <UserTag
                      id={d.id}
                      key={index}
                      name={getEntityName(d)}
                      size={UserTagSize.small}
                    />
                  ))}
                </Space>
              )}
            </div>
            <Form.Item>
              <Space
                className="w-full justify-end"
                data-testid="cta-buttons"
                size={16}>
                <Button
                  data-testid="cancel-glossary"
                  type="link"
                  onClick={onCancel}>
                  {t('label.cancel')}
                </Button>
                <Button
                  data-testid="save-glossary"
                  disabled={!allowAccess}
                  htmlType="submit"
                  loading={isLoading}
                  type="primary">
                  {t('label.save')}
                </Button>
              </Space>
            </Form.Item>
          </Form>
        </div>
      </div>
    </PageLayout>
  );
};

export default AddGlossary;
